/** 二维坐标点 */
export interface IPos {
    x: number
    y: number
}

/** 宽高 */
export interface ISize {
    w: number
    h: number
}

/** 角度 */
export interface IAng {
    ang: number
}

/** 矢量速度 */
export interface IVel extends IAng {
    spd: number
}

/** 二维工具 */
export namespace V2Util {

    const PI = Math.PI
    const PI2 = PI * 2
    const PI_2 = PI / 2
    const PI_RAD = PI / 180
    const PI_ANG = 180 / PI

    export function zero() {
        return { x: 0, y: 0 }
    }

    /** 将角度转为360度制 */
    export function ang360(ang: number) {
        return ang < 0 ? 360 + ang % 360 : ang % 360
    }

    /** 角度转弧度 */
    export function ang2rad(ang: number) {
        return ang * PI_RAD
    }

    /** 弧度转角度 */
    export function rad2ang(rad: number) {
        return rad * PI_ANG
    }

    /** 点1朝向点2的弧度 */
    export function radTo(p1: IPos, p2: IPos) {
        return Math.atan2(p2.y - p1.y, p2.x - p1.x)
    }

    /** 角1与角2的角度差 */
    export function angDiff(a1: number, a2: number) {
        let diff = ang360(a2 - a1)
        return diff > 180 ? diff - 360 : diff
    }

    /** 点朝弧度方向移动后的坐标 */
    export function move(pos: IPos, rad: number, dis: number): IPos {
        let { x, y } = pos
        x += Math.cos(rad) * dis
        y += Math.sin(rad) * dis
        return { x, y }
    }

    /** 点1朝点2方向移动后的坐标 */
    export function moveTo(p1: IPos, p2: IPos, dis: number) {
        return move(p1, radTo(p1, p2), dis)
    }

    /** 点1到点2的距离 */
    export function dis(p1: IPos, p2: IPos) {
        return Math.hypot(p2.x - p1.x, p2.y - p1.y)
    }

    /** 点1在点2的象限 0:右上 */
    export function quadTo(p1: IPos, p2: IPos) {
        let q = Math.floor((radTo(p2, p1) % PI2) / PI_2)
        return <0 | 1 | 2 | 3>(q < 0 ? q + 4 : q)
    }

    /** 点1转换到点2右上象限后的坐标 */
    export function toFirstQuad(p1: IPos, p2: IPos): IPos {
        let { x, y } = p1
        switch (quadTo(p1, p2)) {
            case 1:
                x = Math.abs(x - p2.x)
                break
            case 2:
                x = Math.abs(x - p2.x)
                y = Math.abs(y - p2.y)
                break
            case 3:
                y = Math.abs(y - p2.y)
                break
        }
        return { x, y }
    }
}